package rsshunter;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Scheduler is frequently checking RSSBases for new content.
 */
public class Scheduler {

    private final List<RSSBase> bases;
    private Map<RSSBase, Thread> workers; // Map with workers for every base

    public Scheduler(List<RSSBase> bases) {
        this.bases = bases;
        workers = new HashMap<RSSBase, Thread>();
    }

    public void init() {
        for (RSSBase base : bases) {
            startBase(base);
        }
    }

    /**
     * Update all known bases.
     */
    public void updateAllBases() {
        for (RSSBase base : bases) {
            if (!workers.containsKey(base)) {
                startBase(base);
            }
        }
    }

    /**
     * Starts frequently checking for new content at given RSSBase.
     */
    private void startBase(RSSBase base) {
        Integer notifyFreq = base.getFrequency();
        Thread worker = new Thread(new SchedulerWorker(notifyFreq, base));
        workers.put(base, worker);
        worker.start();
    }

    /**
     * Stop checing for new content at gicen base.
     */
    public void removeBase(RSSBase base) {
        stopThread(base);
        workers.remove(base);
    }

    /*
     * To be used when frequency has changed. It resets base worker and it's
     * timer.
     */
    public void resetBaseWorker(RSSBase base) {
        stopThread(base);
        startBase(base);
    }

    /**
     * Stop worker thread for given RSSBase.
     */
    private void stopThread(RSSBase base) {
        Thread toStop = workers.get(base);
        if (toStop != null) {
            //If thread exists stop it
            toStop.interrupt();
        }
    }

    /**
     * Check RSSBase or new content.
     */
    private synchronized void getNewFeeds(RSSBase base) {
        base.check();
    }

    /**
     * SchedulerWorker is handling one given base for scheduler.
     */
    private class SchedulerWorker implements Runnable {

        private int frequency;
        private RSSBase base;
        private boolean isRunning;

        public SchedulerWorker(int frequency, RSSBase base) {
            this.frequency = frequency;
            this.base = base;
        }

        @Override
        @SuppressWarnings("SleepWhileInLoop")
        public void run() {
            isRunning = true;
            while (isRunning) {
                try {
                    Thread.sleep(frequency * 1000 * 60);
                    getNewFeeds(base);
                } catch (InterruptedException ex) {
                    //Get out of loop and end thread.
                    isRunning = false;
                }
            }
        }
    }
}